﻿// -----------------------------------------------------------------------
// <copyright company="www.3WayWebdesign.de">
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
// 
// <author>Michael Morbach</author>
// <email>Michael@3waywebdesign.de</email>
// <web>http://www.3waywebdesign.de</web>
// ----------------------------------------------------------------------

using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Tww.Wpf.Controls.Native;
using SystemCommands = Microsoft.Windows.Shell.SystemCommands;

namespace Tww.Wpf.Controls.Controls.Windows
{
    [TemplatePart(Name = "PART_Max", Type = typeof (Button))]
    [TemplatePart(Name = "PART_Close", Type = typeof (Button))]
    [TemplatePart(Name = "PART_Min", Type = typeof (Button))]
    public class WindowButtonCommands : ContentControl
    {
        #region Delegates

        public delegate void ClosingWindowEventHandler(object sender, ClosingWindowEventArgs args);

        #endregion

        #region  - Felder (privat) -

        private static string closeText;
        private static string maximize;
        private static string minimize;
        private static string restore;
        private Button close;
        private Button max;
        private Button min;
        private IntPtr user32 = IntPtr.Zero;

        #endregion

        #region  - Konstruktoren -

        static WindowButtonCommands()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof (WindowButtonCommands),
                new FrameworkPropertyMetadata(typeof (WindowButtonCommands)));
        }

        #endregion

        #region  - Indexer und Eigenschaften (öffentlich) -

        public string Minimize
        {
            get
            {
                if (string.IsNullOrEmpty(minimize))
                    minimize = GetCaption(900);
                return minimize;
            }
        }

        public string Maximize
        {
            get
            {
                if (string.IsNullOrEmpty(maximize))
                    maximize = GetCaption(901);
                return maximize;
            }
        }

        public string Close
        {
            get
            {
                if (string.IsNullOrEmpty(closeText))
                    closeText = GetCaption(905);
                return closeText;
            }
        }

        public string Restore
        {
            get
            {
                if (string.IsNullOrEmpty(restore))
                    restore = GetCaption(903);
                return restore;
            }
        }

        #endregion

        #region  - Methoden (öffentlich) -

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            close = Template.FindName("PART_Close", this) as Button;
            if (close != null)
                close.Click += CloseClick;

            max = Template.FindName("PART_Max", this) as Button;
            if (max != null)
                max.Click += MaximiseClick;

            min = Template.FindName("PART_Min", this) as Button;
            if (min != null)
                min.Click += MinimiseClick;

            RefreshMaximiseIconState();
        }

        public void RefreshMaximiseIconState()
        {
            RefreshMaximiseIconState(GetParentWindow());
        }

        #endregion

        #region  - Methoden (privat) -

        protected void OnClosingWindow(ClosingWindowEventArgs args)
        {
            ClosingWindowEventHandler handler = ClosingWindow;
            if (handler != null)
                handler(this, args);
        }

        private string GetCaption(int id)
        {
            if (user32 == IntPtr.Zero)
            {
                user32 = UnsafeNativeMethods.LoadLibrary(Environment.SystemDirectory + "\\User32.dll");
            }

            var sb = new StringBuilder(256);
            UnsafeNativeMethods.LoadString(user32, (uint) id, sb, sb.Capacity);
            return sb.ToString().Replace("&", "");
        }

        private void MinimiseClick(object sender, RoutedEventArgs e)
        {
            Window parentWindow = GetParentWindow();
            if (parentWindow != null)
            {
                SystemCommands.MinimizeWindow(parentWindow);
            }
        }

        private void MaximiseClick(object sender, RoutedEventArgs e)
        {
            Window parentWindow = GetParentWindow();
            if (parentWindow == null)
                return;

            if (parentWindow.WindowState == WindowState.Maximized)
            {
                SystemCommands.RestoreWindow(parentWindow);
            }
            else
            {
                SystemCommands.MaximizeWindow(parentWindow);
            }

            RefreshMaximiseIconState(parentWindow);
        }

        private void RefreshMaximiseIconState(Window parentWindow)
        {
            if (parentWindow == null || max == null)
                return;

            if (parentWindow.WindowState == WindowState.Normal)
            {
                var maxpath = (Path) max.FindName("MaximisePath");
                maxpath.Visibility = Visibility.Visible;

                var restorepath = (Path) max.FindName("RestorePath");
                restorepath.Visibility = Visibility.Collapsed;

                max.ToolTip = Maximize;
            }
            else
            {
                var restorepath = (Path) max.FindName("RestorePath");
                restorepath.Visibility = Visibility.Visible;

                var maxpath = (Path) max.FindName("MaximisePath");
                maxpath.Visibility = Visibility.Collapsed;
                max.ToolTip = Restore;
            }
        }

        private void CloseClick(object sender, RoutedEventArgs e)
        {
            var closingWindowEventHandlerArgs = new ClosingWindowEventArgs();
            OnClosingWindow(closingWindowEventHandlerArgs);

            if (closingWindowEventHandlerArgs.Cancelled)
                return;

            Window parentWindow = GetParentWindow();
            if (parentWindow != null)
            {
                parentWindow.Close();
            }
        }

        private Window GetParentWindow()
        {
            DependencyObject parent = VisualTreeHelper.GetParent(this);

            while (parent != null && !(parent is Window))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }

            var parentWindow = parent as Window;
            return parentWindow;
        }

        #endregion

        public event ClosingWindowEventHandler ClosingWindow;

        ~WindowButtonCommands()
        {
            if (user32 != IntPtr.Zero)
            {
                UnsafeNativeMethods.FreeLibrary(user32);
            }
        }
    }
}